# -*- coding: utf-8 -*-
# created on 2016/11/30
from sympy import Intersection

from mathsolver.functions.base import *


# 更新等比数列类
class DengBiUpdate001(BaseFunction):
    """
    在等比数列{a_{n}}中,若a_{2}=4,a_{4}=1,则a_{6}=.
    """
    def solver(self, *args):
        assert len(args) == 1
        assert isinstance(args[0], BaseSequence)
        sl = BaseShuLieDengBi(args[0].value)
        self.output.append(sl)
        return self


class DengBiUpdate002(BaseFunction):
    """
    设正项等比数列{a_{n}}的首项a_{1}=\\frac{1}{2},前n项和为S_{n},{2^{10}}{S_{30}}-({2^{10}}+1){S_{20}}+{S_{10}}=0,求{a_{n}}的通项
    """
    def solver(self, *args):
        assert len(args) == 2
        assert isinstance(args[0], BaseSequence)
        text = args[1]
        sl = BaseShuLieDengBi(args[0].value)
        if text.find("正项") >= 0:
            q_range = Interval(0, S.Infinity, True, True)
            sl.qRange = Intersection(sl.qRange, q_range)
            a_range = Interval(0, S.Infinity, True, True)
            sl.aRange = Intersection(sl.aRange, a_range)
        elif text.find("各项") >= 0 and text.find("正") >= 0:
            q_range = Interval(0, S.Infinity, True, True)
            sl.qRange = Intersection(sl.qRange, q_range)
            a_range = Interval(0, S.Infinity, True, True)
            sl.aRange = Intersection(sl.aRange, a_range)
        self.output.append(sl)
        return self


class DengBiUpdate003(BaseFunction):
    """
    更新等比数列类
    eg.设数列{a_{n}}是首项为1,公比为-2的等比数列,则a_{1}+|a_{2}|+a_{3}+|a_{4}|=.
    """
    def solver(self, *args):
        assert not args
        text = args[-1]
        assert text.find("等比数列") >= 0
        sls = [self.known[item] for item in self.known if isinstance(self.known[item], BaseSequence)]
        assert len(sls) == 1
        sl = sls[0]
        dengbi_sl = BaseShuLieDengBi(sl.value)
        dengbi_sl.aValue = sl.aValue
        self.output.append(dengbi_sl)
        return self


class DengBiUpdate004(BaseFunction):
    """
    更新等比数列类
    eg.等比数列3,6,12,24的公比q=.
    """
    def solver(self, *args):
        assert len(args) == 1
        text = args[0]
        assert text.find("等比数列") >= 0
        sl = BaseShuLieDengBi('a_(n)')
        self.output.append(sl)
        s_name = str('S_')
        a_name = sl.aName
        name = a_name + s_name
        sl.name = name
        sl.sName = s_name
        self.output.append(sl)
        return self


class DengBiUpdate(BaseFunction):
    CLS = [DengBiUpdate001, DengBiUpdate002, DengBiUpdate003, DengBiUpdate004]

    def solver(self, *args):
        r = None
        for cl in DengBiUpdate.CLS:
            try:
                r = cl(known=self.known, verbose=True).solver(*args)
                break
            except Exception:
                pass
        if not r:
            raise 'try fail'
        return r


class DengBiShouXiangUpdate(BaseFunction):
    """
    等比数列首项不为零
    """
    def solver(self, *args):
        assert len(args) == 1
        seq = args[0].sympify()
        answer = {}
        if 'Sequations' in self.known:
            seqs = self.search('Sequations')
        else:
            seqs = []
        p = r'[a-zA-Z]_\(.*?\)'
        m = re.findall(p, str(seq))
        m = set(m)
        m = list(m)
        assert len(m) == 1
        new_item = sympify(m[0])
        new_item_name = new_item.func
        sl = self.search(str(new_item_name))
        a_name = sl.aName
        self.steps.append(["", "%s" % BaseIneq([a_name(1), "!=", S.Zero]).printing()])
        seqs.append([a_name(1), "!=", S.Zero])
        answer['Sequations'] = seqs
        self.output.append(BaseShuLieValue(answer))
        return self


class DengBiDiZengUpdate(BaseFunction):
    """
    已知数列{a_{n}}是递增的等比数列,a_{1}+a_{4}=9,a_{2}a_{3}=8.求数列{a_{n}}的通项公式
    """
    def solver(self, *args):
        assert len(args) == 1
        seq = args[0].sympify()
        answer = {}
        if 'Sequations' in self.known:
            seqs = self.search('Sequations')
        else:
            seqs = []
        p = r'[a-zA-Z]_\(.*?\)'
        m = re.findall(p, str(seq))
        m = set(m)
        m = list(m)
        assert len(m) == 1
        new_item = sympify(m[0])
        new_item_name = new_item.func
        sl = self.search(str(new_item_name))
        a_name = sl.aName
        a_name = sympify(a_name)
        q_value = sl.qValue
        if q_value is None:
            q_value = sympify('a_(q)')
        ineqs1 = [[a_name(1), ">", 0], [q_value, ">", 1]]
        ineqs2 = [[a_name(1), "<", 0], [q_value, ">", 0], [q_value, "<", 0]]
        seqs.append([ineqs1, ineqs2])
        answer['Sequations'] = seqs
        self.steps.append(["", "∵ %s是递增的等比数列" % (new_latex(seq))])
        self.steps.append(["", "∴ %s 或 %s" % (BaseIneqs(ineqs1).printing(), BaseIneqs(ineqs2).printing())])
        self.output.append(BaseShuLieValue(answer))
        return self


class ShuLieTransferGongBi(BaseFunction):
    """
    等比数列{a_{n}}的前n项和为S_{n},已知S_{1},2S_{2},3S_{3}成等差数列,则{a_{n}}的公比为().
    """
    def solver(self, *args):
        if len(args) == 1:
            seq = args[0].sympify()
            seq_name = seq.func
            sl = self.search(str(seq_name))
        else:
            sls = [self.known[item] for item in self.known if isinstance(self.known[item], BaseSequence)]
            assert len(sls) == 1
            sl = sls[0]
        q_value = sl.qValue
        if q_value is None:
            q_value = 'q'
            sl.qValue = sympify('q')
        self.output.append(BaseVariable(q_value))
        return self


class DengBiLimitSUpdate(BaseFunction):
    """
    如果无穷等比数列{b_{n}}各项的和S=\\frac{1}{3}
    """
    def solver(self, *args):
        assert len(args) == 2
        seq = args[0].sympify()
        if isinstance(args[1], BaseEq):
            left, right = args[1].sympify()
            value = right
        seq_name = seq.func
        sl = self.search(str(seq_name))
        a_name = sl.aName
        q_name = sl.qName
        answer = {}
        if 'Sequations' in self.known:
            seqs = self.search('Sequations')
        else:
            seqs = []
        seqs.append([a_name(1) / (1 - q_name), value])
        answer['Sequations'] = seqs
        self.output.append(BaseShuLieValue(answer))
        return self
